home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 127_01.zip / RAP1.C < prev    next >
Text File  |  1993-06-17  |  17KB  |  598 lines

  1. /*********************************************************************\
  2. ** .---------------------------------------------------------------. **
  3. ** |                                                               | **
  4. ** |                                                               | **
  5. ** |         Copyright (c) 1981, 1982, 1983 by Eric Martz.         | **
  6. ** |                                                               | **
  7. ** |                                                               | **
  8. ** |       Permission is hereby granted to use this source         | **
  9. ** |       code only for non-profit purposes. Publication of       | **
  10. ** |       all or any part of this source code, as well as         | **
  11. ** |       use for business purposes is forbidden without          | **
  12. ** |       written permission of the author and copyright          | **
  13. ** |       holder:                                                 | **
  14. ** |                                                               | **
  15. ** |                          Eric Martz                           | **
  16. ** |                         POWER  TOOLS                          | **
  17. ** |                    48 Hunter's Hill Circle                    | **
  18. ** |                      Amherst MA 01002 USA                     | **
  19. ** |                                                               | **
  20. ** |                                                               | **
  21. ** `---------------------------------------------------------------' **
  22. \*********************************************************************/
  23.  
  24. #include "rap.h"
  25.     
  26. /*****************************************************************
  27.     this function decodes the command type, returning the type, or
  28.         UNKNOWN.
  29. *******************************************************************/
  30. int comtyp (line)
  31.     char *line;
  32.     {
  33.     char let1, let2;
  34.  
  35.     let1  =  toupper( line[1] );
  36.     let2  =  toupper( line[2] );
  37.  
  38.     if ( let1 EQ 'A' && let2 EQ 'R')    return( AR );
  39.     if ( let1 EQ 'B' && let2 EQ 'D')    return( BD );
  40.     if ( let1 EQ 'B' && let2 EQ 'L')    return( BL );
  41.     if ( let1 EQ 'B' && let2 EQ 'O')    return( BO );
  42.     if ( let1 EQ 'B' && let2 EQ 'P')    return( BP );
  43.     if ( let1 EQ 'B' && let2 EQ 'R')    return( BR );
  44.     if ( let1 EQ 'C' && let2 EQ 'C')    return( CC );
  45.     if ( let1 EQ 'C' && let2 EQ 'E')    return( CE );
  46.     if ( let1 EQ 'C' && let2 EQ 'F')    return( CF );
  47.     if ( let1 EQ 'D' && let2 EQ '1')    return( D1 );
  48.     if ( let1 EQ 'D' && let2 EQ '2')    return( D2 );
  49. #ifdef DEBUG
  50.     if ( let1 EQ 'D' && let2 EQ 'E')    return( DEBUG );
  51. #endif
  52.     if ( let1 EQ 'E' && let2 EQ 'C')    return( EC );
  53.     if ( let1 EQ 'E' && let2 EQ 'D')    return( ED );
  54.     if ( let1 EQ 'F' && let2 EQ 'I')    return( FI );
  55.     if ( let1 EQ 'F' && let2 EQ 'O')    return( FO );
  56.     if ( let1 EQ 'F' && let2 EQ 'N')    return( FN );
  57.     if ( let1 EQ 'H' && let2 EQ 'E')    return( HE );
  58.     if ( let1 EQ 'I' && let2 EQ '@')    return( IAT);
  59.     if ( let1 EQ 'I' && let2 EQ 'C')    return( IC );
  60.     if ( let1 EQ 'I' && let2 EQ 'G')    return( IG );
  61.     if ( let1 EQ 'I' && let2 EQ 'N')    return( IN );
  62.     if ( let1 EQ 'I' && let2 EQ 'X')    return( IX );
  63.     if ( let1 EQ 'J' && let2 EQ 'U')    return( JU );
  64.     if ( let1 EQ 'L' && let2 EQ 'F')    return( LF );
  65.     if ( let1 EQ 'L' && let2 EQ 'S')    return( LS );
  66.     
  67.     if ( let1 EQ 'M') {
  68.          if (let2 EQ '1')            return( M1 );
  69.         if (let2 EQ '2')            return( M2 );
  70.         if (let2 EQ '3')            return( M3 );
  71.         if (let2 EQ '4')            return( M4 );
  72.         if (let2 EQ 'O')            return( MO );
  73.     }
  74.  
  75.     if ( let1 EQ 'N' && let2 EQ 'E')    return( NEED );
  76.     if ( let1 EQ 'N' && let2 EQ 'F')    return( NF );
  77.     if ( let1 EQ 'N' && let2 EQ 'J')    return( NJ );
  78.     if ( let1 EQ 'N' && let2 EQ 'X')    return( NX );
  79.  
  80.     if ( let1 EQ 'O' && let2 EQ 'U')    return( OU );
  81.     if ( let1 EQ 'P' && let2 EQ '#')    return( PNO );
  82.     if ( let1 EQ 'P' && let2 EQ 'D')    return( PD );
  83.     if ( let1 EQ 'P' && let2 EQ 'I')    return( PI );
  84.     if ( let1 EQ 'P' && let2 EQ 'L')    return( PL );
  85.     if ( let1 EQ 'R' && let2 EQ 'E')    return( RE );
  86.     if ( let1 EQ 'R' && let2 EQ 'M')    return( RM );
  87.     if ( let1 EQ 'R' && let2 EQ 'F')    return( RF );
  88.     if ( let1 EQ 'S' && let2 EQ 'A')    return( SA );
  89.     if ( let1 EQ 'S' && let2 EQ 'P')    return( SP );
  90.     if ( let1 EQ 'S' && let2 EQ 'S')    return( SS );
  91.     if ( let1 EQ 'T' && let2 EQ 'A')    return( TA );
  92.     if ( let1 EQ 'T' && let2 EQ 'C')    return( TC );
  93.     if ( let1 EQ 'T' && let2 EQ 'I')    return( TI );
  94.     if ( let1 EQ 'U' && let2 EQ 'L')    return( UL );
  95.  
  96.     if ( let1 EQ Pre_ss_delim &&
  97.         let2 EQ Pre_ss_delim)    return( PRE_SS );
  98.     if ( let1 EQ Post_ss_delim &&
  99.         let2 EQ Post_ss_delim)    return( POST_SS );
  100.  
  101.     return( UNKNOWN );        /* no match */
  102. }
  103. /*********************************************************************
  104.     Skips white-space characters at the beginning of a string.
  105. *********************************************************************/
  106. skip_blanks ( string )
  107.     char *string;
  108.     {
  109.     char local[ MAXLINE ];
  110.     int i, j, k;
  111.  
  112.     
  113.  
  114.     strcpy ( local, string );
  115.  
  116.     for (i = 0;
  117.         (local[i] EQ ' ' || local[i] EQ '\t' || local[i] EQ '\n');
  118.         i++);
  119.  
  120.     for (j = 0; (string[j] = local[i])  NE  '\0' ; i++, j++ )    ;
  121.  
  122.     return;
  123. }
  124.  
  125.     
  126. /*********************************************************************
  127.  
  128.     Truncates white-space characters at the end of a string.
  129.  
  130. *********************************************************************/
  131. trunc_bl (string)
  132.     char *string;
  133.     {
  134.     char *ptr;
  135.     int k;
  136.  
  137.     k  =  strlen (string);
  138.     ptr  =  &string[ k-1 ];    /* char before terminating nul */
  139.  
  140.     while (*ptr EQ BLANK || *ptr EQ TAB || *ptr EQ NEWLINE)    
  141.         *ptr--   =  '\0';
  142. }
  143.     
  144. /*******************************************************************
  145.     performs the formatting command returned by comtyp - sets global
  146.       variables ( indenting, underlining, etc. )
  147. *******************************************************************/
  148.  
  149. command (line, nx, valid)
  150.     char *line, *nx;
  151.     int *valid;
  152.     {
  153.     int c_type;    /* command type  */
  154.     int arg_val;    /* argument value, if any */
  155.     char arg_sign;    /* relative (+ or -) or absolute */
  156.     int i;
  157.  
  158.     c_type  =  comtyp (line);
  159. #ifdef DEBUG
  160.     if (Debug) fprintf(STDERR,"COMMAND %d\n",c_type);
  161. #endif
  162.  
  163.     if (c_type  EQ  UNKNOWN)    /* IGNORE ALIEN ORDERS */
  164.         {
  165.         fprintf(STDERR,
  166.             "UNKNOWN COMMAND at line %d: <%s>\n",In_linecnt,line);
  167.         *valid = NO;
  168.         return(0);
  169.     }
  170.     *valid = YES;
  171.  
  172.     arg_val  =  get_val ( line, &arg_sign );
  173. #ifdef DEBUG
  174.     if (Debug) fprintf(STDERR,
  175.         "get_val returned arg_val = %d, arg_sign =  %c   \n",
  176.         arg_val, arg_sign);
  177. #endif
  178.     switch (c_type) {
  179.  
  180.         case AR : /* assign value to arabic {#{ */
  181.             set(&Arabic, arg_val, arg_sign, 1, 0, 32000);
  182.             break;
  183.  
  184.         case TC: /* table of contents */
  185.             if (Tabcont) extract(line+4);
  186.             break;
  187.             
  188.         case IX: /* index */
  189.             if (Index) extract(line+4);
  190.             break;
  191.             
  192.         case PD: /* print draft */
  193.             set(&Printdraft, arg_val, arg_sign, 1, 0, 1);
  194.             break;
  195.             
  196.         case BD: /* begin draft */
  197.             Indraft = YES;
  198.             break;
  199.             
  200.         case ED: /* end draft */
  201.             Indraft = NO;
  202.             break;
  203.  
  204.         case FI :    /* filled lines  */
  205.             brk(CR);    /* flush out last unfilled */
  206.             Fill  =  YES;
  207.             Tival = Pival;
  208.             break;
  209.  
  210.         case NEED: /* need arg_val lines */
  211.             if ((arg_val + Lineno - 1) > Bottom) space(HUGE);
  212.             break;
  213.  
  214.         case NF :    /* non-filled lines */
  215.             brk(CR);    /* flush out */
  216.             Fill  =  NO;
  217.             Tival = Inval;
  218.             break;    /* down and cry */
  219.  
  220.         case BR :    /* just cause a break */
  221.             brk(CR);
  222.             Tival = Pival;
  223.             break;
  224.  
  225.         case LS :    /* set line spacing value */
  226.             set (&Lsval, arg_val, arg_sign, 1, 1, HUGE );
  227.             break;
  228.  
  229.         case TI :    /* set temporary left indent */
  230.             brk(CR);
  231.             set ( &Tival, arg_val, arg_sign, 5, 0, Rmval );
  232.             break;
  233.  
  234.         case PI : /* set paragraph indent */
  235.             set (&Pival, arg_val, arg_sign, Inval+5, -HUGE, HUGE);
  236.             brk(CR);
  237.             if (Fill) Tival = Pival;
  238.             break;
  239.  
  240.         case IN :    /* set left indent */
  241.             brk(CR);
  242.             set ( &Inval, arg_val, arg_sign, 0, 0, Rmval-1 );
  243.             Pival = Inval;
  244.             if (Fill) Tival = Pival;
  245.             else Tival = Inval;
  246.             break;
  247.  
  248.         case RM:    /* set right margin */
  249.             set ( &Rmval, arg_val, arg_sign, 78, Tival+1, HUGE );
  250.             break;
  251.  
  252.         case RF:    /* restore font to primary/default */
  253.             if ( /*Sanders AND*/ Font_o)
  254.                 printf("%s%d%s", Font_o, Font, Font_c);
  255.             break;
  256.  
  257.         case M1:    /* set topmost margin */
  258.             set ( &M1val, arg_val, arg_sign, 2, 0, HUGE);
  259.             break;
  260.  
  261.         case M2:    /* set second top margin */
  262.             set ( &M2val, arg_val, arg_sign, 2, 0, HUGE);
  263.             break;
  264.  
  265.         case M3:    /* set first bottom margin */
  266.             set ( &M3val, arg_val, arg_sign, 2, 0, HUGE);
  267.             break;
  268.  
  269.         case M4:    /* set bottom-most margin */
  270.             set ( &M4val, arg_val, arg_sign, 2, 0, HUGE);
  271.             break;
  272.  
  273.         case MO:    /* restore mode on sanders */
  274.             brk(CR);
  275.             /*if (Sanders)*/ restore_mode();/*??does nothing if Print_at*/
  276.             break;
  277.  
  278.         case CE :    /* center next arg_val lines */
  279.             brk(CR);
  280.             set ( &Ce_input, arg_val, arg_sign, 1, 0, HUGE);
  281.             break;
  282. #ifdef DEBUG
  283.         case DEBUG : /* Turn on Debug */
  284.             Debug = YES;
  285.             checkbig("Debug ON\n","");
  286.             break;
  287. #endif
  288.         case EC : /* expand control character flag */
  289.             set(&Exp_ctrl_chars,
  290.                 arg_val, arg_sign, YES, NO, YES);
  291.             break;
  292.  
  293.         case UL :    /* underline next arg_val lines */
  294.             set ( &Ul_input, arg_val, arg_sign, 1, 1, HUGE );
  295.             break;
  296.             
  297.         case BO :
  298.             set ( &Bo_input, arg_val, arg_sign, 1, 1, HUGE );
  299.             break;
  300.  
  301.         case HE :    /* get header title for pages */
  302.             gettl ( line, Header );
  303.             break;
  304.  
  305.         case FO :    /* get footer title for pages */
  306.             gettl ( line, Footer );
  307.             break;
  308.  
  309.         case SP :    /* space down arg_val blank lines */
  310.             set (&Spval, arg_val, arg_sign, 1, 0, HUGE);
  311.             space ( Spval );
  312.             break;
  313.  
  314.         case BP :    /* set pageno arg_val - begin page */
  315.             if ( Lineno > 0 OR Outbuf[0])    space (HUGE);
  316.             set ( &Curpag, arg_val, arg_sign, Curpag+1, -HUGE, HUGE);
  317.             Newpag  =  Curpag;
  318.             break;
  319.  
  320.         case PNO: /* assign new value to page number
  321.                 without forcing page break */
  322.             set (&Curpag, arg_val, arg_sign, 1, 0, 32000);
  323.             Newpag = Curpag + 1;
  324.             break;
  325.  
  326.         case PL :    /* set page length */
  327.             set (&Plval, arg_val, arg_sign, 66,
  328.                 M1val+M2val+M3val+M4val+1, HUGE);
  329.             Bottom  =  Plval - M3val - M4val;
  330.             break;
  331.  
  332.         case TA : /* set tab modulus */
  333.             set (&Tabval, arg_val, arg_sign, 5, 1, HUGE);
  334.             break;
  335.  
  336.         case JU : /* Justify */
  337.             set(&Justify, arg_val, arg_sign, 1, 0, 2);
  338.             /*if (Sanders)*/ restore_mode();
  339.             break;
  340.  
  341.         case NJ : /* no justify */
  342.             if (Justify EQ YES) brk(CR);
  343.             Justify = NO;
  344.             break;
  345.  
  346.         case NX : /* next input file */
  347.             gettl (line, nx);
  348.             break;
  349.     
  350.         case FN : /* select primary font */
  351.             set(&Font, arg_val, arg_sign, 0, 0, 16);
  352.             if (/*Sanders AND*/ Font_o)
  353.                 printf("%s%d%s", Font_o, arg_val, Font_c);
  354.             break;
  355.  
  356.         case SA : /* Sanders printer? 0=no, 1=yes */
  357.             set(&Sanders, arg_val, arg_sign, YES, 0, 1);
  358.             break;
  359.  
  360.         case PRE_SS : /* {{ delimited ss, 0=no, 1=yes */
  361.             set(&Pre_ss, arg_val, arg_sign, 1, 0, 1);
  362.             break;
  363.  
  364.         case POST_SS : /* }} delimited ss, 0=no, 1=yes */
  365. /*            if (!Post_ss AND arg_val) brk(CR); */
  366.             set(&Post_ss, arg_val, arg_sign, 1, 0, 1);
  367.             break;
  368.         
  369.         case RE : /* read sub input file */
  370.             read_command(line);
  371. /*            if (New_portion) find_portion();*/
  372.             break;
  373.         
  374.         case SS : /* input ss pairs */
  375.             if (!arg_val) {
  376.                 fprintf(STDERR,
  377. "Error: '.ss 0' without preceding 'ss 1' at line %d\n", In_linecnt);
  378.                 break;
  379.             }
  380.             getpairs(Fpin, ((Fp_main EQ Fpin)? Fn_main: Fn_read));
  381.             break;
  382.  
  383.         case OU : /* set output flag */
  384.                 switch (arg_val) {
  385.                 case 1:
  386.                     Screen_size = SCREEN_SIZE;
  387.                     _Outflag |= arg_val;
  388.                     break;
  389.                 case 2:
  390.                 case 4:
  391.                 case 8:
  392.                     _Outflag |= arg_val;
  393.                     if (!(_Outflag & 1)) Screen_size = 0;
  394.                     break;
  395.                 case 12:
  396.                 case 14:
  397.                 case 16:
  398.                 case 18:
  399.                 case 20:
  400.                 case 22:
  401.                 case 24:
  402.                 case 26:
  403.                 case 28:
  404.                 case 30:
  405.                 case 40:
  406.                 case 54:
  407.                 case 60:
  408.                     _Outflag |= 1;
  409.                     Screen_size = arg_val;
  410.                     break;
  411.                 default:
  412.                     fprintf(STDERR,"Invalid '.ou' argument\n");
  413.                     exit(0);
  414.             }
  415.             break;
  416.  
  417.         case D1 :
  418.             if (strlen(line) >= 5) Pre_ss_delim = line[4];
  419.             else Pre_ss_delim = '{';
  420.             break;
  421.  
  422.         case D2 :
  423.             if (strlen(line) >= 5) Post_ss_delim = line[4];
  424.             else Post_ss_delim = '}';
  425.             break;
  426.  
  427.         case IAT: /* Ignore @ as first char in input line */
  428.             set(&Ignore_at, arg_val, arg_sign, 1, 0, 1);
  429.             break;
  430.  
  431.         case IC : /* Ignore commands */
  432.             set(&i, arg_val, arg_sign, 1, 0, 1);
  433.             return(i);
  434.  
  435.         case IG : /* Ignore input line */
  436.             break;
  437.             
  438.         case CF : /* continuous forms */
  439.             set(&Con_forms, arg_val, arg_sign, 1, 0, 1);
  440.             break;
  441.             
  442.         case BL : /* blank out character */
  443.             if (strlen(line) >= 5) Blank_c = line[4];
  444.             else Blank_c = ' ';
  445.             break;
  446.  
  447.         case CC : /* compress control characters */
  448.             set(&Comp_carat, arg_val, arg_sign, 1, 0, 1);
  449.             break;
  450.             
  451.         case LF : /* on: NL -> CR+LF; off: NL -> CR only, and
  452.                 CR -> RLF, CR */
  453.             set(&i, arg_val, arg_sign, 1, 0, 1);
  454.             i? Suppress_lf = NO: Suppress_lf = YES; /* invert logic */
  455.             break;
  456.     }
  457.     return(0);
  458. }
  459.  
  460. /******************************************************************
  461.  
  462.     gets the number ( if any ) associated with any command 
  463.  
  464. *******************************************************************/
  465. int get_val ( line, typ )
  466.     char *line, *typ;
  467.     {
  468.     int i;
  469.     char local[ MAXLINE ];
  470.  
  471.     strcpy (local, line);    /* local copy */
  472.     if (local[3] EQ NULL) return(NO_VAL);
  473.  
  474.     /* skip over the command line */
  475.     for (i = 1;
  476.         local[i] NE ' ' && local[i] NE '\t' && local[i] NE '\n';
  477.         i++ )
  478.     ;
  479.  
  480.     skip_blanks (&local[i]);    /* find the number */
  481.     if (local[i] EQ NULL) return(NO_VAL);
  482.     *typ  =  local[i];    /* relative or absolute */
  483.  
  484.     if ( *typ EQ '+' || *typ EQ '-' )    i++;
  485.     else if ( !isdigit( *typ ) )    return( NO_VAL );
  486.     ati(&i,local+i);
  487.     return(i);
  488. }
  489. /*****************************************************************
  490.      sets a global parameter like line-spacing, underlining, etc.
  491.      Also checks that the new value is within the range of that 
  492.      parameter.  Assigns the default for that parameter if no value
  493.       is specified.
  494. ******************************************************************/
  495.  
  496. set ( param, val, arg_sign, defval, minval, maxval )
  497.     int *param, val, defval, minval, maxval;
  498.     char arg_sign;
  499.     {
  500.     if (val  EQ  NO_VAL )        /* defaulted */
  501.         *param  =  defval;
  502.     else if (arg_sign  EQ  '+')    /* relative + */
  503.         *param +=  val;
  504.     else if (arg_sign  EQ  '-')    /* relative - */
  505.         *param -=  val;
  506.     else    *param  =  val;        /* absolute */
  507.  
  508.     *param  =  min (*param,maxval);
  509.     *param  =  max (*param, minval);
  510. #ifdef DEBUG
  511.     if (Debug) fprintf(STDERR,"SET *param  =  %d\n", *param);
  512. #endif
  513.     return;
  514. }
  515.  
  516. /**********************************************************
  517.             centers a line of text
  518. **********************************************************/
  519. center (line)
  520.     char *line;
  521.     {
  522.     Tival  =  max(( Rmval+Tival-truelen(line))/2, 0 );
  523.     return;
  524. }
  525.     
  526. /*****************************************************************
  527.         distibute words evenly across a line
  528. *****************************************************************/
  529. spread ( line, nextra, no_words)
  530.     char *line;
  531.     int nextra;    /* no. extra places left in line */
  532.     int no_words;   /* no. words in the line         */
  533.     {
  534.     int i, j, nblanks, nholes;
  535. #ifdef DEBUG
  536.     if (Debug) fprintf(STDERR,
  537. "spread:line = <%s>, nextra = %d, no_words = %d\n",
  538.         line, nextra, no_words);
  539. #endif
  540.     if (nextra <=  0 || no_words <=  1)    return;
  541.  
  542.     Dir  =  !(Dir);
  543.     nholes  =  no_words - 1;
  544.     trunc_bl (line);
  545.     i  =  strlen(line) - 1 ; /* last character of string */
  546.     j  =  min (MAXLINE - 2,  i + nextra);/* last position in output */
  547.     line[j+1]  =  '\0';
  548. #ifdef DEBUG
  549.     if (Debug) fprintf(STDERR,
  550.         "Dir = %d, nholes = %d, i = %d, j = %d\n",
  551.         Dir, nholes, i, j);
  552. #endif
  553.     for ( ; i<j ; i--, j-- )
  554.           { line[j]  =  line[i];
  555. #ifdef DEBUG
  556.         if (Debug) fprintf(STDERR,
  557.             "[%c i = %d j = %d] ", line[j], i, j);
  558. #endif
  559.         if ( line[i]  EQ  BLANK)
  560.               { if (Dir  EQ  0)
  561.                 nblanks  =  (nextra - 1)/nholes   +   1;
  562.             else
  563.                 nblanks  =  nextra/nholes;
  564.             nextra  =  nextra - nblanks;
  565.             nholes  =  nholes - 1;
  566. #ifdef DEBUG
  567.             if (Debug) fprintf(STDERR,
  568.                 "nblanks = %d, nextra = %d\n",
  569.                 nblanks, nextra);
  570. #endif
  571.             for ( ; nblanks > 0;  nblanks-- )
  572.                 line[--j]  =  BLANK;
  573.               }
  574.           }
  575. #ifdef DEBUG
  576.     if (Debug) fprintf(STDERR,"after spreading, line is:\n<%s>\n", line);
  577. #endif
  578.     return;
  579.     }
  580.  
  581. /*****************************************************************/
  582. extract(buf)
  583.     char *buf;
  584.     {
  585.     char number[8];
  586.     
  587.     sprintf(number, "%d", Curpag);
  588.     substitute(buf, "#", number);
  589.     substitute(buf, "$F", (Fpin EQ Fp_main? Fn_main: Fn_read));
  590.  
  591.     puts(buf);
  592.     putchar(NEWLINE);
  593. }
  594. /*****************************************************************
  595.     END OF RAP1.C
  596. *****************************************************************/
  597. (Debug) fprintf(STDERR,
  598.             "